package com.the_last.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.the_last.constant.RedisKeyConstant;
import com.the_last.mapper.*;
import com.the_last.pojo.dto.IncrementalRolePermissionDTO;
import com.the_last.pojo.dto.SysRoleDTO;
import com.the_last.pojo.po.SysPermission;
import com.the_last.pojo.po.SysRole;
import com.the_last.pojo.po.SysRolePermission;
import com.the_last.pojo.po.SysUserRole;
import com.the_last.service.ISysRoleService;
import com.the_last.service.ISysUserRoleService;
import com.the_last.utils.RedisUtil;
import com.the_last.utils.Result;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
        implements ISysRoleService {
    
    private final SysRolePermissionMapper rolePermissionMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final SysPermissionMapper permissionMapper;
    private final RedisUtil redisUtil;
    private final UserMapper userMapper;
    @Getter
    private final ISysUserRoleService sysUserRoleService;
    private final RedissonClient redissonClient;
    
    @Override
    public Result<Page<SysRole>> getRoleList(Page<SysRole> page, SysRoleDTO queryDTO) {
        try {
            LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
            
            // 查询条件
            if (StringUtils.hasText(queryDTO.getRoleName())) {
                queryWrapper.like(SysRole::getRoleName, queryDTO.getRoleName());
            }
            if (StringUtils.hasText(queryDTO.getRoleCode())) {
                queryWrapper.like(SysRole::getRoleCode, queryDTO.getRoleCode());
            }
            if (queryDTO.getStatus() != null) {
                queryWrapper.eq(SysRole::getStatus, queryDTO.getStatus());
            }
            
            // 排除已删除的角色
            queryWrapper.eq(SysRole::getDeleted, 0);
            queryWrapper.orderByDesc(SysRole::getCreatedTime);
            
            Page<SysRole> result = page(page, queryWrapper);
            return Result.success(result);
            
        } catch (Exception e) {
            log.error("获取角色列表失败", e);
            return Result.fail("获取角色列表失败");
        }
    }
    
    @Override
    public Result<List<SysRole>> getRolesByUserId(Long userId) {
        if (userId == null) {
            return Result.fail("用户ID不能为空");
        }
        
        try {
            String cacheKey = "user:roles:" + userId;
            @SuppressWarnings("unchecked")
            List<SysRole> cachedRoles = redisUtil.getObject(cacheKey, List.class);
            if (cachedRoles != null) {
                return Result.success(cachedRoles);
            }
            
            List<SysRole> roles = baseMapper.selectRolesByUserId(userId);
            if (roles != null) {
                redisUtil.set(cacheKey, roles, 300); // 5分钟缓存
            }
            return Result.success(roles);
        } catch (Exception e) {
            log.error("查询用户角色失败，userId: {}", userId, e);
            return Result.fail("查询用户角色失败");
        }
    }
    
    @Override
    public Result<Void> addRole(SysRole role) {
        if (role == null) {
            return Result.fail("角色信息不能为空");
        }
        
        if (role.getRoleCode() == null || role.getRoleName() == null) {
            return Result.fail("角色编码和名称不能为空");
        }
        
        try {
            QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("role_code", role.getRoleCode())
                    .eq("deleted", 0);
            
            if (count(queryWrapper) > 0) {
                return Result.fail("角色编码已存在");
            }
            
            role.setCreatedTime(LocalDateTime.now());
            role.setUpdatedTime(LocalDateTime.now());
            role.setStatus(1);
            role.setDeleted(0);
            
            save(role);
            
            // 清除有效角色ID缓存
            clearValidRoleIdsCache();
            
            return Result.success();
        } catch (Exception e) {
            log.error("新增角色失败", e);
            return Result.fail("新增角色失败");
        }
    }
    
    private void clearValidRoleIdsCache() {
        redisUtil.delete(RedisKeyConstant.VALID_ROLE_IDS_KEY);
    }
    
    @Override
    public Result<Void> updateRole(SysRole role) {
        if (role == null || role.getId() == null) {
            return Result.fail("角色ID不能为空");
        }
        
        try {
            SysRole existingRole = getById(role.getId());
            if (existingRole == null || existingRole.getDeleted().equals(1)) {
                return Result.fail("角色不存在");
            }
            
            if (role.getRoleCode() != null &&
                    !role.getRoleCode().equals(existingRole.getRoleCode())) {
                QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("role_code", role.getRoleCode())
                        .eq("deleted", 0)
                        .ne("id", role.getId());
                
                if (count(queryWrapper) > 0) {
                    return Result.fail("角色编码已存在");
                }
            }
            
            role.setUpdatedTime(LocalDateTime.now());
            updateById(role);
            
            // 清除有效角色ID缓存
            clearValidRoleIdsCache();
            
            return Result.success();
        } catch (Exception e) {
            log.error("更新角色失败", e);
            return Result.fail("更新角色失败");
        }
    }
    
    @Override
    @Transactional
    public Result<Void> deleteRole(Long id) {
        if (id == null) {
            return Result.fail("角色ID不能为空");
        }
        
        try {
            SysRole role = getById(id);
            if (role == null) {
                return Result.fail("角色不存在");
            }
            
            QueryWrapper<SysUserRole> userRoleQuery = new QueryWrapper<>();
            userRoleQuery.eq("role_id", id).eq("deleted", 0);
            
            if (userRoleMapper.selectCount(userRoleQuery) > 0) {
                return Result.fail("该角色已分配给用户，无法删除");
            }
            role.setUpdatedTime(LocalDateTime.now());
            removeById(role);
            
            QueryWrapper<SysRolePermission> rolePermissionQuery = new QueryWrapper<>();
            rolePermissionQuery.eq("role_id", id).eq("deleted", 0);
            
            rolePermissionMapper.delete(rolePermissionQuery);
            
            // 更新相关用户的权限版本号
            updateUserPermVersionByRoleId(id);
            
            // 清除有效角色ID缓存
            clearValidRoleIdsCache();
            
            return Result.success();
        } catch (Exception e) {
            log.error("删除角色失败，id: {}", id, e);
            return Result.fail("删除角色失败");
        }
    }
    
    @Override
    @Transactional
    public Result<Void> assignPermissionsToRole(Long roleId, List<Long> permissionIds) {
        if (roleId == null) {
            return Result.fail("角色ID不能为空");
        }
        
        try {
            SysRole role = getById(roleId);
            if (role == null || role.getDeleted().equals(1)) {
                return Result.fail("角色不存在");
            }
            
            QueryWrapper<SysRolePermission> deleteQuery = new QueryWrapper<>();
            deleteQuery.eq("role_id", roleId);
            rolePermissionMapper.delete(deleteQuery);
            
            if (!CollectionUtils.isEmpty(permissionIds)) {
                // 验证权限有效性（使用缓存）
                Set<Long> validPermissionIds = getValidPermissionIds();
                List<Long> filteredPermissionIds = permissionIds.stream()
                        .distinct() // 去重
                        .filter(validPermissionIds::contains) // 只保留有效的权限ID
                        .toList();
                
                if (filteredPermissionIds.size() != permissionIds.size()) {
                    return Result.fail("存在无效的权限");
                }
                
                List<SysRolePermission> rolePermissions = filteredPermissionIds.stream()
                        .map(permissionId -> {
                            SysRolePermission rp = new SysRolePermission();
                            rp.setRoleId(roleId);
                            rp.setPermissionId(permissionId);
                            rp.setCreatedTime(LocalDateTime.now());
                            rp.setDeleted(0);
                            return rp;
                        }).collect(Collectors.toList());
                
                rolePermissionMapper.insertBatch(rolePermissions);
            }
            
            // 权限分配完成
            updateUserPermVersionByRoleId(roleId);
            return Result.success();
        } catch (Exception e) {
            log.error("角色分配权限失败，roleId: {}", roleId, e);
            return Result.fail("角色分配权限失败");
        }
    }
    
    @Override
    @Transactional
    public Result<Void> incrementalAssignRolePermissions(IncrementalRolePermissionDTO incrementalDTO) {
        if (incrementalDTO == null || incrementalDTO.getRoleId() == null) {
            return Result.fail("角色ID不能为空");
        }
        
        if (!incrementalDTO.hasValidOperation()) {
            return Result.fail("至少需要指定一个操作：添加权限或删除权限");
        }
        
        Long roleId = incrementalDTO.getRoleId();
        List<Long> addPermissionIds = incrementalDTO.getAddPermissionIds();
        List<Long> removePermissionIds = incrementalDTO.getRemovePermissionIds();
        
        try {
            // 1. 验证角色存在
            SysRole role = getById(roleId);
            if (role == null || role.getDeleted().equals(1)) {
                return Result.fail("角色不存在");
            }
            
            // 2. 处理权限删除操作
            if (removePermissionIds != null && !removePermissionIds.isEmpty()) {
                Result<Void> removeResult = removePermissionsFromRole(roleId, removePermissionIds);
                if (removeResult.getCode() != 200) {
                    return Result.fail("删除权限失败: " + removeResult.getMsg());
                }
            }
            
            // 3. 处理权限添加操作
            if (addPermissionIds != null && !addPermissionIds.isEmpty()) {
                // 验证权限有效性（使用缓存）
                Set<Long> validPermissionIds = getValidPermissionIds();
                List<Long> filteredAddPermissionIds = addPermissionIds.stream()
                        .distinct() // 去重
                        .filter(validPermissionIds::contains) // 只保留有效的权限ID
                        .toList();
                
                if (filteredAddPermissionIds.size() != addPermissionIds.size()) {
                    return Result.fail("存在无效的权限");
                }
                
                // 直接创建新的角色权限关联记录（不做重复检查）
                List<SysRolePermission> rolePermissions = filteredAddPermissionIds.stream()
                        .map(permissionId -> {
                            SysRolePermission rp = new SysRolePermission();
                            rp.setRoleId(roleId);
                            rp.setPermissionId(permissionId);
                            rp.setCreatedTime(LocalDateTime.now());
                            rp.setDeleted(0);
                            return rp;
                        }).toList();
                
                rolePermissionMapper.insertBatch(rolePermissions);
                log.info("角色[{}]新增权限{}个", roleId, rolePermissions.size());
            }
            
            // 4. 更新用户权限版本（如果有任何变更）
            updateUserPermVersionByRoleId(roleId);
            
            return Result.success();
        } catch (Exception e) {
            log.error("增量分配角色权限失败，roleId: {}", roleId, e);
            return Result.fail("增量分配角色权限失败");
        }
    }
    
    @Override
    public Result<List<SysRole>> getAllActiveRoles() {
        try {
            
            QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 1)
                    .eq("deleted", 0)
                    .orderByAsc("role_code");
            
            List<SysRole> roles = list(queryWrapper);
            return Result.success(roles);
        } catch (Exception e) {
            log.error("查询所有有效角色失败", e);
            return Result.fail("查询角色列表失败");
        }
    }
    
    @Override
    public Result<Void> updateRoleStatus(List<Long> roleIds, Integer status) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Result.fail("角色ID列表不能为空");
        }
        
        if (status == null || (status != 0 && status != 1)) {
            return Result.fail("状态值无效");
        }
        
        try {
            List<SysRole> roles = listByIds(roleIds);
            if (CollectionUtils.isEmpty(roles)) {
                return Result.fail("角色不存在");
            }
            
            roles.forEach(role -> {
                if (!role.getDeleted().equals(1)) {
                    role.setStatus(status);
                    role.setUpdatedTime(LocalDateTime.now());
                    updateById(role);
                }
            });
            
            // 清除有效角色ID缓存
            clearValidRoleIdsCache();
            
            return Result.success();
        } catch (Exception e) {
            log.error("更新角色状态失败", e);
            return Result.fail("更新角色状态失败");
        }
    }
    
    @Override
    public Result<List<Long>> getRoleIdsByUserId(Long userId) {
        if (userId == null) {
            return Result.fail("用户ID不能为空");
        }
        
        try {
            QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", userId).eq("deleted", 0);
            List<SysUserRole> userRoles = userRoleMapper.selectList(queryWrapper);
            
            List<Long> roleIds = userRoles.stream()
                    .map(SysUserRole::getRoleId)
                    .collect(Collectors.toList());
            
            return Result.success(roleIds);
        } catch (Exception e) {
            log.error("查询用户角色ID失败，userId: {}", userId, e);
            return Result.fail("查询用户角色ID失败");
        }
    }
    
    @Override
    public Result<List<SysPermission>> getPermissionsByRoleId(Long roleId) {
        if (roleId == null) {
            return Result.fail("角色ID不能为空");
        }
        
        try {
            List<SysPermission> permissions = baseMapper.selectPermissionsByRoleId(roleId);
            return Result.success(permissions);
        } catch (Exception e) {
            log.error("查询角色权限失败，roleId: {}", roleId, e);
            return Result.fail("查询角色权限失败");
        }
    }
    
    @Override
    @Transactional
    public Result<Void> removePermissionsFromRole(Long roleId, List<Long> permissionIds) {
        if (roleId == null) {
            return Result.fail("角色ID不能为空");
        }
        
        if (CollectionUtils.isEmpty(permissionIds)) {
            return Result.fail("权限ID列表不能为空");
        }
        
        try {
            SysRole role = getById(roleId);
            if (role == null || role.getDeleted().equals(1)) {
                return Result.fail("角色不存在");
            }
            
            QueryWrapper<SysRolePermission> deleteQuery = new QueryWrapper<>();
            deleteQuery.eq("role_id", roleId)
                    .in("permission_id", permissionIds)
                    .eq("deleted", 0);
            
            List<SysRolePermission> rolePermissions = rolePermissionMapper.selectList(deleteQuery);
            if (!CollectionUtils.isEmpty(rolePermissions)) {
                rolePermissionMapper.deleteByIds(rolePermissions);
            }
            
            // 更新相关用户的权限版本号
            updateUserPermVersionByRoleId(roleId);
            return Result.success();
        } catch (Exception e) {
            log.error("移除角色权限失败，roleId: {}, permissionIds: {}", roleId, permissionIds, e);
            return Result.fail("移除角色权限失败");
        }
    }
    
    /**
     * 更新指定角色相关用户的权限版本号
     * 当角色权限发生变化时调用
     *
     * @param roleId 角色ID
     */
    private void updateUserPermVersionByRoleId(Long roleId) {
        try {
            List<Long> userIds = userMapper.selectUserIdsByRoleId(roleId);
            if (!CollectionUtils.isEmpty(userIds)) {
                userMapper.batchUpdatePermVersion(userIds);
                // 批量删除permVersion缓存
                List<String> deleteKeyList = userIds.stream().map(userId -> RedisKeyConstant.USER_PERM_VERSION_KEY + userId).toList();
                redisUtil.delete(deleteKeyList);
                log.info("已更新 {} 个用户的权限版本号，角色ID: {}", userIds.size(), roleId);
            }
        } catch (Exception e) {
            log.error("更新用户权限版本号失败，角色ID: {}", roleId, e);
        }
    }
    
    /**
     * 更新指定用户的权限版本号
     * 当用户角色发生变化时调用
     *
     * @param userIds 用户ID列表
     */
    private void updateUserPermVersionByUserIds(List<Long> userIds) {
        // TODO 还需要删除对应缓存
        try {
            if (!CollectionUtils.isEmpty(userIds)) {
                userMapper.batchUpdatePermVersion(userIds);
                log.info("已更新 {} 个用户的权限版本号", userIds.size());
            }
        } catch (Exception e) {
            log.error("更新用户权限版本号失败，用户IDs: {}", userIds, e);
        }
    }
    
    /**
     * 获取有效的权限ID列表（带缓存）
     *
     * @return 有效权限ID集合
     */
    private Set<Long> getValidPermissionIds() {
        // 先从缓存获取
        Set<Long> cachedPermissionIds = redisUtil.getSet(RedisKeyConstant.VALID_PERMISSION_IDS_KEY, Long.class);
        if (!CollectionUtils.isEmpty(cachedPermissionIds)) {
            return cachedPermissionIds;
        }
        return loadAndCacheValidPermissionIds();
    }
    
    /**
     * 从数据库加载有效权限ID并缓存
     *
     * @return 有效权限ID集合
     */
    private Set<Long> loadAndCacheValidPermissionIds() {
        RLock lock = redissonClient.getLock(RedisKeyConstant.VALID_PERMISSION_IDS_LOCK_KEY);
        try {
            // 尝试获取锁，最多等待3秒，锁定10秒后自动释放
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                try {
                    Set<Long> cachedPermissionIds = redisUtil.getSet(RedisKeyConstant.VALID_PERMISSION_IDS_KEY, Long.class);
                    if (!CollectionUtils.isEmpty(cachedPermissionIds)) {
                        return cachedPermissionIds;
                    }
                    
                    // 从数据库查询有效权限ID
                    QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("status", 1)
                            .eq("deleted", 0)
                            .select("id");
                    
                    List<SysPermission> validPermissions = permissionMapper.selectList(queryWrapper);
                    Set<Long> validPermissionIds = validPermissions.stream()
                            .map(SysPermission::getId)
                            .collect(Collectors.toSet());
                    
                    // 缓存30分钟
                    redisUtil.addToSet(RedisKeyConstant.VALID_PERMISSION_IDS_KEY, validPermissionIds);
                    
                    log.info("已缓存有效权限ID列表，共{}个权限", validPermissionIds.size());
                    return validPermissionIds;
                } finally {
                    lock.unlock();
                }
            } else {
                // 获取锁失败，直接查询数据库
                log.warn("获取权限缓存锁失败，直接查询数据库");
                return queryValidPermissionIdsFromDb();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("获取权限缓存锁时被中断", e);
            return queryValidPermissionIdsFromDb();
        } catch (Exception e) {
            log.error("加载权限缓存时发生异常", e);
            return queryValidPermissionIdsFromDb();
        }
    }
    
    /**
     * 直接从数据库查询有效权限ID（不使用缓存）
     *
     * @return 有效权限ID集合
     */
    private Set<Long> queryValidPermissionIdsFromDb() {
        QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1)
                .eq("deleted", 0)
                .select("id");
        
        List<SysPermission> validPermissions = permissionMapper.selectList(queryWrapper);
        return validPermissions.stream()
                .map(SysPermission::getId)
                .collect(Collectors.toSet());
    }
    
}